﻿using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Web.Mvc;
using eCRAM.Bll;
using eCRAM.Dao;
using eCRAM.Model;
using eCRAM.Model.CustomModel;
using eCRAM.Tools;
using eCRAM.WebSite.Attributes;
using eCRAM.WebSite.Models;
using eCRAM.WebSite.Tools;

namespace eCRAM.WebSite.Controllers
{
    [CustomAuthorization(UserRole.ProjectLeader, UserRole.Administrator)]
    public class ReferenceDataController : Controller
    {
        /// <summary>
        /// Affiche la liste des données de référence
        /// </summary>
        /// <returns></returns>
        [AcceptVerbs("Get", "Post")]
        public ActionResult Index()
        {
            return View("Index", new ReferentialsDataModel());
        }


        public ActionResult SelectDataType(int? dataType)
        {
            if (!dataType.HasValue || dataType == 0)
            {
                return View("Index", new ReferentialsDataModel());

            }
            ReferentialsDataModel model;
            switch ((EnumDataType)dataType)
            {
                case EnumDataType.Activites:

                    var table = new TableDescription<EditActivityModel>
                                    {
                                        EditActionName = "EditActivity",
                                        HiddenFieldName = "idActivity",
                                        GetKeyMethod = item => item.Id
                                    };
                    table.AddRow(new TableRowDescription<EditActivityModel>("Libellé", item => item.Name));
                    table.AddRow(new TableRowDescription<EditActivityModel>("Date de début", item => item.StartDate.ToShortDateString()));
                    table.AddRow(new TableRowDescription<EditActivityModel>("Date de fin", item => item.EndDate.HasValue
                                                                                ? item.EndDate.Value.ToShortDateString()
                                                                                : ""));
                    table.AddRow(new TableRowDescription<EditActivityModel>("Type", item => item.TypeActivityLabel));
                    table.AddRow(new TableRowDescription<EditActivityModel>("Chef de projet", item => item.ProjectLeaderName));
                    table.AddRow(new TableRowDescription<EditActivityModel>("Est astreinte", item => item.IsAstreinte ? "Oui" : "Non"));
                    table.AddRow(new TableRowDescription<EditActivityModel>("Est actif", item => item.IsActive ? "Oui" : "Non"));

                    model = new ReferentialsDataModel
                                {
                                    AddActionName = "AddActivity",
                                    AddActionLabel = "Ajouter une activité",
                                    Label = "Activités",
                                };
                    model.SetData(
                        ActivityManager.GetAll().Select(EditActivityModel.FromActivity).OrderBy(a => a.Name).ToList());
                    model.SetTableDescription(table);
                    break;
                case EnumDataType.Utilisateurs:

                    var tableUser = new TableDescription<UserModel>
                                        {
                                            EditActionName = "EditUser",
                                            HiddenFieldName = "idUser",
                                            GetKeyMethod = item => item.Id
                                        };
                    tableUser.AddRow(new TableRowDescription<UserModel>("Login", item => item.Login));
                    tableUser.AddRow(new TableRowDescription<UserModel>("Prénom", item => item.FirstName));
                    tableUser.AddRow(new TableRowDescription<UserModel>("Nom", item => item.LastName));
                    tableUser.AddRow(new TableRowDescription<UserModel>("Rôle", item => ((UserRole)item.Role).GetLabel()));
                    tableUser.AddRow(new TableRowDescription<UserModel>("Société", item => item.Company));
                    tableUser.AddRow(new TableRowDescription<UserModel>("E-Mail", item => item.Email));
                    tableUser.AddRow(new TableRowDescription<UserModel>("Nombre de projets", item => item.UserActivities.Count()));
                    tableUser.AddRow(new TableRowDescription<UserModel>("Est Actif", item => item.IsActive ? "Oui" : "Non"));

                    model = new ReferentialsDataModel
                                {
                                    AddActionName = "AddUser",
                                    AddActionLabel = "Ajouter un utilisateur",
                                    Label = "Utilisateurs",
                                };
                    model.SetData(UserManager.GetAll().Select(UserModel.FromUser).OrderBy(u => u.Login).ToList());
                    model.SetTableDescription(tableUser);
                    break;
                case EnumDataType.Parametres:
                     var tableparam = new TableDescription<ParameterModel>
                                        {
                                            EditActionName = "EditParameter",
                                            HiddenFieldName = "idParameter",
                                            GetKeyMethod = item => item.Id
                                        };
                     tableparam.AddRow(new TableRowDescription<ParameterModel>("Nom", item => item.Name));
                     tableparam.AddRow(new TableRowDescription<ParameterModel>("Description", item => item.Description));
                     tableparam.AddRow(new TableRowDescription<ParameterModel>("Valeur", item => item.Value));

                    model = new ReferentialsDataModel
                                {
                                    Label = "Paramètres de l'application",
                                };
                    model.SetData(ParameterRepository.GetAll().Select(ParameterModel.FromParameter).OrderBy(u => u.Name).ToList());
                    model.SetTableDescription(tableparam);
                    break;
                
                case EnumDataType.ExportCram:

                    var tableExport = new TableDescription<CramSummary>();
                    tableExport.AddRow(new TableRowDescription<CramSummary>("Mois", item =>  string.Format("{0} {1}", CultureInfo.CurrentCulture.DateTimeFormat.MonthNames[item.Month-1].Capitalize(), item.Year)));
                    tableExport.AddRow(new TableRowDescription<CramSummary>("Nouveaux", item => item.NbNew));
                    tableExport.AddRow(new TableRowDescription<CramSummary>("Soumis", item => item.NbSubmit));
                    tableExport.AddRow(new TableRowDescription<CramSummary>("Validés partiellement", item => item.NbPartialValidated));
                    tableExport.AddRow(new TableRowDescription<CramSummary>("Validés", item => item.NbValidated));
                    tableExport.AddRow(new TableRowDescription<CramSummary>("Approuvés partiellement", item => item.NbPartialApproved));
                    tableExport.AddRow(new TableRowDescription<CramSummary>("Approuvés", item => item.NbApproved));
                    

                    model = new ReferentialsDataModel
                                {
                                    //AddActionName = "ExportCrams",
                                    //AddActionLabel = "Exporter tous les crams",
                                    Label = "Récapitulatif des crams",
                                };
                    model.SetData(CramRepository.GetCramsSummary().OrderByDescending(s => s.Year).ThenByDescending(s => s.Month));
                    model.SetTableDescription(tableExport);
                    break;
                default:
                    throw new ArgumentOutOfRangeException("dataType");
            }
            model.DataType = dataType.Value;
            return View("Index", model);
        }

        #region Paramètre

        /// <summary>
        /// Ajout d'une nouvelle activité
        /// </summary>
        /// <returns></returns>
        public ActionResult EditParameter(Guid idParameter)
        {
            var param = ParameterRepository.GetById(idParameter);
            var model = ParameterModel.FromParameter(param);
            return DisplayParameterEditView(model);
        }

        /// <summary>
        /// Affiche la vue de création / modification d'un parametre
        /// </summary>
        /// <param name="model"></param>
        /// <returns></returns>
        private ActionResult DisplayParameterEditView(ParameterModel model)
        {
            return View("EditParameter", model);
        }

        /// <summary>
        /// Valide les modifications apportées au paramètre
        /// </summary>
        /// <param name="model"></param>
        /// <returns></returns>
        public ActionResult ValidateParameter(ParameterModel model)
        {
            if (!ModelState.IsValid)
            {
                return DisplayParameterEditView(model);
            }

            var param = model.ToParameter();
            ParameterRepository.Update(param);
            return SelectDataType((int)EnumDataType.Parametres);
        }
        #endregion

        #region Activity

        /// <summary>
        /// Ajout d'une nouvelle activité
        /// </summary>
        /// <returns></returns>
        public ActionResult AddActivity()
        {
            return DisplayActivityEditView(new EditActivityModel());
        }

        /// <summary>
        /// Ajout d'une nouvelle activité
        /// </summary>
        /// <returns></returns>
        public ActionResult EditActivity(Guid idActivity)
        {
            var activity = ActivityManager.GetActivityById(idActivity);
            var model = EditActivityModel.FromActivity(activity);
            return DisplayActivityEditView(model);
        }


        /// <summary>
        /// Affiche la vue de création / modification d'une activité
        /// </summary>
        /// <param name="model"></param>
        /// <returns></returns>
        private ActionResult DisplayActivityEditView(EditActivityModel model)
        {
            ViewData["listActivityTypes"] = ActivityManager.GetAllActivityTypes();
            return View("EditActivity", model);
        }

        /// <summary>
        /// Valide les modifications apportées à l'activité
        /// </summary>
        /// <param name="model"></param>
        /// <returns></returns>
        [HttpPost]
        public ActionResult ValidateActivity(EditActivityModel model)
        {
            if (!ModelState.IsValid)
            {
                return DisplayActivityEditView(model);
            }

            var activity = model.ToActivity();
            if (activity.Id == Guid.Empty)
            {
                ActivityManager.Create(activity);
            }
            else
            {
                ActivityManager.Update(activity);
            }
            return SelectDataType((int)EnumDataType.Activites);
        }


        #endregion

        #region Utilisateurs

        /// <summary>
        /// Ajout d'un utilisateur
        /// </summary>
        /// <returns></returns>
        public ActionResult AddUser()
        {
            return DisplayUserEditView(new UserModel(), null);
        }

        /// <summary>
        /// Modification d'un utilisateur
        /// </summary>
        /// <param name="idUser"></param>
        /// <param name="userActivitiesList"></param>
        /// <returns></returns>
        public ActionResult EditUser(Guid idUser, IEnumerable<UserActivityModel> userActivitiesList)
        {
            var user = UserManager.GetUserById(idUser);
            var model = UserModel.FromUser(user);

            return DisplayUserEditView(model, userActivitiesList);
        }

        /// <summary>
        ///  Valide les modifications apportées à l'utilisateur
        /// </summary>
        /// <param name="model"></param>
        /// <param name="userActivities"></param>
        /// <returns></returns>
        [HttpPost]
        public ActionResult ValidateUser(UserModel model, UserActivityModel[] userActivities)
        {
            if (!ModelState.IsValid)
            {
                return DisplayUserEditView(model, userActivities);
            }

            var user = model.ToUser();
            if (user.Id == Guid.Empty)
            {
                UserManager.Create(user);
            }
            else
            {
                UserManager.Update(user);
            }

            if (userActivities != null)
            {
                foreach (var userActivity in userActivities.Select(UserActivityModel.ToUserActivity))
                {
                    userActivity.UserId = user.Id;

                    if (userActivity.Status == ObjectStatus.New)
                    {
                        userActivity.Id = Guid.NewGuid();
                        UserRepository.AddUserActivity(userActivity);
                    }
                    else if (userActivity.Status == ObjectStatus.Deleted && userActivity.Id != Guid.Empty)
                    {
                        UserRepository.DeleteUserActivity(userActivity.Id);
                    }

                }
            }
            return SelectDataType((int)EnumDataType.Utilisateurs);
        }

        /// <summary>
        /// Affiche le formulaire de création / modification d'un utilisateur
        /// </summary>
        /// <param name="model"></param>
        /// <param name="userActivities"></param>
        /// <returns></returns>
        private ActionResult DisplayUserEditView(UserModel model, IEnumerable<UserActivityModel> userActivities)
        {
            if (userActivities != null)
            {
                model.UserActivities = userActivities;
            }
            return View("EditUser", model);
        }

        /// <summary>
        /// Suppression de l'association entre une activité et un utilisateur
        /// </summary>
        /// <param name="model"></param>
        /// <param name="id"></param>
        /// <param name="idUserActivity"></param>
        /// <param name="userActivities"></param>
        /// <returns></returns>
        [HttpPost]
        public ActionResult DeleteUserActivity(UserModel model, Guid id, Guid idUserActivity, UserActivityModel[] userActivities)
        {
            var list = userActivities.ToList();
            var item = list.Find(u => u.Id == idUserActivity);
            if (item.Id == Guid.Empty)
            {
                list.Remove(item);
            }
            else
            {
                item.Status = ObjectStatus.Deleted;
            }
            return DisplayUserEditView(model, list);
        }

        /// <summary>
        /// Ajout d'une association entre un utilisateur et une activité
        /// </summary>
        /// <param name="model"></param>
        /// <param name="id"></param>
        /// <param name="idActivity"></param>
        /// <param name="userActivities"></param>
        /// <returns></returns>
        [HttpPost]
        public ActionResult AddUserActivity(UserModel model, Guid id, Guid idActivity, UserActivityModel[] userActivities)
        {
            var item = new User_Activity { Id = Guid.Empty, UserId = id, ActivityId = idActivity, Status = ObjectStatus.New, Activity = ActivityRepository.GetById(idActivity) };
            var list = userActivities != null ? userActivities.ToList() : new List<UserActivityModel>();
            list.Add(UserActivityModel.FromUserActivity(item));
            return DisplayUserEditView(model, list);
        }
        #endregion

    
    }
}
